package org.aurora.framework.boot.data.mybatis.configure;

import com.mybatisflex.core.FlexGlobalConfig;
import com.mybatisflex.core.audit.AuditManager;
import com.mybatisflex.core.audit.ConsoleMessageCollector;
import com.mybatisflex.core.audit.MessageCollector;
import com.mybatisflex.core.datasource.DataSourceDecipher;
import com.mybatisflex.core.mybatis.FlexConfiguration;
import com.mybatisflex.spring.boot.ConfigurationCustomizer;
import com.mybatisflex.spring.boot.MyBatisFlexCustomizer;
import com.mybatisflex.spring.boot.MybatisFlexAutoConfiguration;
import org.apache.ibatis.logging.stdout.StdOutImpl;
import org.aurora.framework.boot.data.common.dataobject.AuditDO;
import org.aurora.framework.boot.data.mybatis.audit.AuditInsertListener;
import org.aurora.framework.boot.data.mybatis.audit.AuditUpdateListener;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;

import java.util.Objects;

/**
 * name: MyBatisFlexAutoConfiguration
 * <p>
 * desc: MyBatis-Flex auto configuration class
 * <p>
 * create date: 2024-09-25 16:43:31
 *
 * @author cao.yong
 */
@AutoConfiguration
@AutoConfigureAfter(MybatisFlexAutoConfiguration.class)
@EnableConfigurationProperties({MyBatisFlexCustomProperties.class})
@ConditionalOnProperty(prefix = MyBatisFlexCustomProperties.CONFIG_PREFIX, name = "enabled", havingValue = "true")
public class MyBatisFlexAutoConfiguration implements ConfigurationCustomizer, MyBatisFlexCustomizer {

    private final MyBatisFlexCustomProperties properties;

    public MyBatisFlexAutoConfiguration(MyBatisFlexCustomProperties properties) {
        this.properties = properties;
    }

    /**
     * Data source configuration information decryption algorithm object
     *
     * @return Decryption algorithm object
     */
    @Bean
    public DataSourceDecipher dataSourceDecipher() {
        // No encryption has been applied to the configuration data here, so it is returned as is
        return (dataSourceProperty, value) -> value;
    }

    @Override
    public void customize(FlexConfiguration configuration) {
        if (properties.showSql()) {
            configuration.setLogImpl(StdOutImpl.class);
        }
    }

    @Override
    public void customize(FlexGlobalConfig flexGlobalConfig) {
        // Register audit listener
        flexGlobalConfig.registerInsertListener(new AuditInsertListener(), AuditDO.class);
        flexGlobalConfig.registerUpdateListener(new AuditUpdateListener(), AuditDO.class);
        // Determine whether the audit function is enabled
        if (properties.enableAudit()) {
            // Enable audit
            AuditManager.setAuditEnable(true);
            // Set Audit SQL Collector
            MessageCollector collector = new ConsoleMessageCollector();
            AuditManager.setMessageCollector(collector);
        }
        // Determine whether the tenant function is enabled
        if (properties.enableTenant()) {
            flexGlobalConfig.setTenantColumn(properties.tenantField());
        }
        // Determine whether the logic delete function is enabled
        if (properties.enableLogicDelete()) {
            flexGlobalConfig.setLogicDeleteColumn(properties.logicDeleteField());
        }
        // Determine whether the optimistic lock function and set column name
        if (Objects.nonNull(properties.versionField()) && !properties.versionField().isEmpty()) {
            flexGlobalConfig.setVersionColumn(properties.versionField());
        }
    }
}
